#ifndef __SFC_H__
#define __SFC_H__

#include <common.h>
#include <spi.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>

#define SFC_CTRL0_OFFSET                    (0x00)
#define SFC_CTRL1_OFFSET                    (0x04)
#define SFC_SSIENR_OFFSET                   (0x08)
#define SFC_MWCR_OFFSET                     (0x0c)
#define SFC_SER_OFFSET                      (0x10)
#define SFC_BAUD_OFFSET                     (0x14)
#define SFC_TXFTL_OFFSET                    (0x18)
#define SFC_RXFTL_OFFSET                    (0x1c)
#define SFC_TXFL_OFFSET                     (0x20)
#define SFC_RXFL_OFFSET                     (0x24)
#define SFC_STATUS_OFFSET                   (0x28)
#define SFC_IMR_OFFSET                      (0x2c)
#define SFC_ISR_OFFSET                      (0x30)
#define SFC_RISR_OFFSET                     (0x34)
#define SFC_TXOIC_OFFSET                    (0x38)
#define SFC_RXOIC_OFFSET                    (0x3c)
#define SFC_RXUIC_OFFSET                    (0x40)
#define SFC_MSTIC_OFFSET                    (0x44)
#define SFC_INTCLR_OFFSET                   (0x48)
#define SFC_DMACTRL_OFFSET                  (0x4c)
#define SFC_DMATDL_OFFSET                   (0x50)
#define SFC_DMARDL_OFFSET                   (0x54)
#define SFC_IDR_OFFSET                      (0x58)
#define SFC_SSI_COMPVER_OFFSET              (0x5c)
#define SFC_DATA_OFFSET                     (0x60)
#define SFC_SAMPLE_DELAY                    (0xf0)
#define SFC_CCFGR_OFFSET                    (0xf4)
#define SFC_OPCR_OFFSET                     (0xf8)
#define SFC_TIMCR_OFFSET                    (0xfc)
#define SFC_NFC_CMD_MODE                    (0x100)
#define SFC_NFC_ACCESS_START                (0x104)
#define SFC_NFC_CMD_SET0                    (0x108)
#define SFC_NFC_CMD_SET1                    (0x10c)
#define SFC_NFC_CMD_SET2                    (0x110)
#define SFC_NFC_ECC_INFO                    (0x114)
#define SFC_SPARE_BUFFER                    (0xf00)
#define SFC_PAGE_DATA_BUFFER                (0x1000)

#define REG_SFC_CTRL0(n)                    (n + SFC_CTRL0_OFFSET)
#define REG_SFC_CTRL1(n)                    (n + SFC_CTRL1_OFFSET)
#define REG_SFC_SSIENR(n)                   (n + SFC_SSIENR_OFFSET)
#define REG_SFC_MWCR(n)                     (n + SFC_MWCR_OFFSET)
#define REG_SFC_SER(n)                      (n + SFC_SER_OFFSET)
#define REG_SFC_BAUD(n)                     (n + SFC_BAUD_OFFSET)
#define REG_SFC_TXFTL(n)                    (n + SFC_TXFTL_OFFSET)
#define REG_SFC_RXFTL(n)                    (n + SFC_RXFTL_OFFSET)
#define REG_SFC_TXFL(n)                     (n + SFC_TXFL_OFFSET)
#define REG_SFC_RXFL(n)                     (n + SFC_RXFL_OFFSET)
#define REG_SFC_STATUS(n)                   (n + SFC_STATUS_OFFSET)
#define REG_SFC_IMR(n)                      (n + SFC_IMR_OFFSET)
#define REG_SFC_ISR(n)                      (n + SFC_ISR_OFFSET)
#define REG_SFC_RISR(n)                     (n + SFC_RISR_OFFSET)
#define REG_SFC_TXOIC(n)                    (n + SFC_TXOIC_OFFSET)
#define REG_SFC_RXOIC(n)                    (n + SFC_RXOIC_OFFSET)
#define REG_SFC_RXUIC(n)                    (n + SFC_RXUIC_OFFSET)
#define REG_SFC_MSTIC(n)                    (n + SFC_MSTIC_OFFSET)
#define REG_SFC_INTCLR(n)                   (n + SFC_INTCLR_OFFSET)
#define REG_SFC_DMACTRL(n)                  (n + SFC_DMACTRL_OFFSET)
#define REG_SFC_DMATDL(n)                   (n + SFC_DMATDL_OFFSET)
#define REG_SFC_DMARDL(n)                   (n + SFC_DMARDL_OFFSET)
#define REG_SFC_IDR(n)                      (n + SFC_IDR_OFFSET)
#define REG_SFC_SSI_COMPVER(n)              (n + SFC_SSI_COMPVER_OFFSET)
#define REG_SFC_DATA(n)                     (n + SFC_DATA_OFFSET)
#define REG_SFC_SAMPLE_DELAY(n)             (n + SFC_SAMPLE_DELAY)
#define REG_SFC_CCFGR(n)                    (n + SFC_CCFGR_OFFSET)
#define REG_SFC_OPCR(n)                     (n + SFC_OPCR_OFFSET)
#define REG_SFC_TIMCR(n)                    (n + SFC_TIMCR_OFFSET)
#define REG_SFC_NFC_CMD_MODE(n)             (n + SFC_NFC_CMD_MODE)
#define REG_SFC_NFC_ACCESS_START(n)         (n + SFC_NFC_ACCESS_START)
#define REG_SFC_NFC_CMD_SET0(n)             (n + SFC_NFC_CMD_SET0)
#define REG_SFC_NFC_CMD_SET1(n)             (n + SFC_NFC_CMD_SET1)
#define REG_SFC_NFC_CMD_SET2(n)             (n + SFC_NFC_CMD_SET2)
#define REG_SFC_NFC_ECC_INFO(n)             (n + SFC_NFC_ECC_INFO)
#define REG_SFC_SPARE_BUFFER(n)             (n + SFC_SPARE_BUFFER)
#define REG_SFC_PAGE_DATA_BUFFER(n)         (n + SFC_PAGE_DATA_BUFFER)


/* NFC_ACCESS_START Register bits. */
#define NFC_ACC_START                       BIT(0)

/* NFC_CMD_SET0 Register bits. */
#define NFC_ADDR_LENGTH_OFFSET              0
#define NFC_ADDR_LENGTH_SIZE                3
#define NFC_SPARE_LENGTH_OFFSET             8
#define NFC_SPARE_LENGTH_SIZE               6
#define NFC_DATA_LENGTH_OFFSET              16
#define NFC_DATA_LENGTH_SIZE                12

/* NFC_CMD_SET1 Register bits. */
#define NFC_CMD_VALUE_OFFSET                0
#define NFC_CMD_VALUE_SIZE                  8
#define NFC_ADDR1_OFFSET                    8
#define NFC_ADDR1_SIZE                      8
#define NFC_ADDR2_OFFSET                    16
#define NFC_ADDR2_SIZE                      8
#define NFC_ADDR3_OFFSET                    24
#define NFC_ADDR3_SIZE                      8

/* NFC_CMD_MODE Register bits. */
#define NFC_WRITE_CMD                       BIT(0)
#define NFC_READ_CMD                        BIT(1)
#define ECC_CAL_EB                          BIT(2)
#define DATA_TYPE_OFFSET                    3
#define DATA_TYPE_SIZE                      2
#define DATA_NONE                           (0x0)
#define DATA_ONLY                           (0x1)
#define DATA_WITH_SPARE                     (0x2)
#define SPI_XF_MODE_OFFSET                  (8)
#define SPI_XF_MODE_SIZE                    (2)
#define DMA_MODE                            BIT(10)

#define SFC_DMA_MAX_LEN                     (4096)
#define SPI_RX_ONLY_ONE_TIME_SIZE           (4096)
#define SPI_TX_ONLY_ONE_TIME_SIZE           (256)

#define ADDR1_MASK                          GENMASK(15, 8)
#define ADDR1(x)                            ((x) << 8)
#define ADDR2_MASK                          GENMASK(23, 16)
#define ADDR2(x)                            ((x) << 16)
#define ADDR3_MASK                          GENMASK(31, 24)
#define ADDR3(x)                            ((x) << 24)
#define ADDR4_MASK                          GENMASK(7, 0)
#define ADDR4(x)                            ((x) << 0)
#define ADDR5_MASK                          GENMASK(15, 8)
#define ADDR5(x)                            ((x) << 8)

typedef enum enum_spi_enable
{
    SPI_DISABLE = 0,
    SPI_ENABLE  = (lift_shift_bit_num(0)),
} spi_enable_e;

/* polarity */
typedef enum enum_spi_polarity
{
    SPI_POLARITY_LOW   = 0,
    SPI_POLARITY_HIGH  = (lift_shift_bit_num(7)),
    SPI_POLARITY_RANGE = (lift_shift_bit_num(7)),
} spi_polarity_e;

/* phase */
typedef enum enum_spi_phase
{
    SPI_PHASE_RX_FIRST = 0,
    SPI_PHASE_TX_FIRST = (lift_shift_bit_num(6)),
    SPI_PHASE_RANGE    = (lift_shift_bit_num(6)),
} spi_phase_e;

typedef enum enum_spi_format
{
    SPI_MOTOROLA_MODE      = 0x00,
    SPI_TI_MODE            = 0x10,
    SPI_MICROWIRE_MODE     = 0x20,
    SPI_FRAME_FORMAT_RANGE = 0x30,
} spi_format_e;

typedef enum enum_spi_data_size
{
    SPI_DATA_SIZE_4BIT  = 0x03,
    SPI_DATA_SIZE_5BIT  = 0x04,
    SPI_DATA_SIZE_6BIT  = 0x05,
    SPI_DATA_SIZE_7BIT  = 0x06,
    SPI_DATA_SIZE_8BIT  = 0x07,
    SPI_DATA_SIZE_9BIT  = 0x08,
    SPI_DATA_SIZE_10BIT = 0x09,
    SPI_DATA_SIZE_RANGE = 0x0f,
} spi_data_size_e;

typedef enum enum_spi_transfer_mode {
    SPI_TX_RX_MODE   = 0x000,
    SPI_ONLY_TX_MODE = 0x100,
    SPI_ONLY_RX_MODE = 0x200,
    SPI_EEPROM_MODE  = 0x300,
    SPI_TRANSFER_MODE_RANGE = 0x300,
} spi_transfer_mode_e;

typedef enum enum_spi_data_type {
    SPI_DATA_NONE    = (0x00 << 3),
    SPI_DATA_ONLY    = (0x01 << 3),
    SPI_DATA_SPARE   = (0x10 << 3),
    SPI_DATA_ALL     = (0x11 << 3),
} spi_data_type_e;


typedef enum enum_spi_baudrate {
    SPI_SCLKIN = 100000000,
} spi_baudrate_e;

typedef enum enum_spi_irq {
    SPI_IRQ_TXEIM = (lift_shift_bit_num(0)),
    SPI_IRQ_TXOIM = (lift_shift_bit_num(1)),
    SPI_IRQ_RXUIM = (lift_shift_bit_num(2)),
    SPI_IRQ_RXOIM = (lift_shift_bit_num(3)),
    SPI_IRQ_RXFIM = (lift_shift_bit_num(4)),
    SPI_IRQ_MSTIM = (lift_shift_bit_num(5)),
    SPI_IRQ_ALL   = 0x3f,
} spi_irq_e;

typedef struct _sfc_controller {
    unsigned int base;
    unsigned int freq; /* Default frequency */
    unsigned int mode;
    struct spi_slave slave;
    unsigned int transfer_mode;
    unsigned int rx_hw_hand;
    unsigned int tx_hw_hand;
    unsigned int clk_in;
    unsigned int sample_delay;
} sfc_controller;


static inline sfc_controller *to_fh_sfc(struct spi_slave *slave)
{
    return container_of(slave, sfc_controller, slave);
}

#endif
